﻿using Levfier.GUI.EditorControls.Chains;
using Levfier.GUI.EditorControls.Exceptions;
using Levfier.Proccessors.ArithmeticLogicUnits;
using System;
using System.Windows.Media;

namespace Levfier.GUI.EditorControls.ArithmeticLogicUnits
{
    /// <summary>
    /// HardClipperControl.xaml の相互作用ロジック
    /// </summary>
    [Serializable]
    public partial class AdderControl : ProccessorControl
    {
        /// <summary>
        /// コントロールの名前
        /// </summary>
        public static readonly string ControlName = "Adder";

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public AdderControl()
        {
            InitializeComponent();
            this.proccessor = new Adder();
            this.upperChainConnectionMaxNum = 10;
        }

        /// <summary>
        /// 選択された時の動作
        /// 末端の子クラスで実装すること
        /// </summary>
        /// <param name="sender">イベント発生源</param>
        public override void Select(object sender)
        {
            this.border.BorderBrush = this.selectedBrush;
        }

        /// <summary>
        /// 選択解除された時の動作
        /// 末端の子クラスで実装すること
        /// </summary>
        /// <param name="sender">イベント発生源</param>
        public override void Unselect(object sender)
        {
            this.border.BorderBrush = Brushes.Transparent;
        }

        /// <summary>
        /// 経路チェック
        /// </summary>
        /// <returns>出力まで到達できなかった末端経路数</returns>
        /// <exception cref="RouteLoopException">経路に循環が発生した場合に発生</exception>
        public override int CheckRoute()
        {
            //通過回数をインクリメント
            this.PassedThroughCount++;

            //通過した回数が上流チェインの数より多い場合、ループと判定
            //ただし、上流チェインが0の場合、例外を吐かない
            if (0 != upperChainControls.Count && upperChainControls.Count < this.PassedThroughCount)
            {
                //画面でキャッチすること
                throw new RouteLoopException("接続の循環が発生しました。", null);
            }

            //末端の場合（出力に到達していない場合）
            if (0 == this.lowerChainControls.Count)
            {
                return 1;
            }

            //下流で出力に到達していない経路数を合計する
            int sum = 0;
            foreach (IChainControl chainControl in this.lowerChainControls)
            {
                sum += chainControl.CheckRoute();

                //加算器なので、後段が複数回呼び出されるため、初期化しておく
                chainControl.InitRouteCheck();
            }

            return sum;
        }
    }
}
